package com.tanhua.server.serivce;


import com.alibaba.fastjson.JSON;
import com.tanhua.commons.template.AipFaceTemplate;
import com.tanhua.commons.template.HuanXinTemplate;
import com.tanhua.commons.template.OssTemplate;
import com.tanhua.commons.template.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.PageResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.domain.vo.UserLikeVo;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FreezeUserApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;

/**
 * 业务类，封装业务操作，专门给控制器使用
 */
@Service
public class UserService {
    /**
     * 注入dubbo服务接口的代理对象，导入dubbo的包
     */
    @Reference
    private UserApi userApi;
    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    // 保存手机验证码到redis中的key的前缀
    private final String SMS_KEY = "sms_key_";
    // 获取token
    @Value("${tanhua.secret}")
    private String secret;
    @Reference
    private UserInfoApi userInfoApi;
    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    @Reference
    private FreezeUserApi freezeUserApi;

    /**
     * 测试1：根据手机号码查询
     */
    public ResponseEntity<Object> findByMobile(String mobile){
        try {
            // 模拟错误
            String str = null;
            str.length();

            User user = userApi.findByMobile(mobile);
            // 方法返回的对象自动转换为json格式的数据
            return ResponseEntity.ok(user);// 自动把对象转换为json后返回
        } catch (Exception e) {
            e.printStackTrace();
            // 保存错误信息
            Map<String,Object> errorMap = new HashMap<>();
            errorMap.put("errorMessage","根据手机号码查询错误!");
            errorMap.put("errCode",100);
            return ResponseEntity.status(500).body(errorMap);
        }
    }
    /**
     * 测试2：保存手机号码
     */
    public ResponseEntity<Object> saveUser(User user){
        Long userId = userApi.save(user);
        return ResponseEntity.ok(userId);
    }

    /**
     * 接口名称：登录第一步---手机号登录
     * 需求描述：给传入的手机号码发送短信验证码
     */
    public ResponseEntity<Object> login(String phone) {
        Long userId = userApi.findByMobile(phone).getId();
        Integer rangeNum = freezeUserApi.findByUserId(userId);
        if (rangeNum == 1){
            return ResponseEntity.status(500).body(ErrorResult.freezeError());
        }
        //1. 生成短信验证码
        String code = (int)((Math.random() * 9 + 1) * 100000) + "";

        //2. 调用工具类发送短信
        //smsTemplate.sendSms(phone,code);
        code = "123456";

        //3  验证码存储到redis，设置有效时间5分钟
        redisTemplate.opsForValue().set(SMS_KEY+phone,code,Duration.ofMinutes(5));
        return ResponseEntity.ok(null);
    }

    @Autowired
    private HuanXinTemplate huanXinTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 接口名称：登录第二步---验证码校验
     * 需求描述：根据用户输入的验证码进行校验
     */
    public ResponseEntity<Object> loginVerification(String phone, String verificationCode) {
        //1. 从redis中获取验证码
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);

        //2. 验证码校验，校验失败给予错误提示.  校验完成，删除redis中的验证码
        if (redisCode == null || !verificationCode.equals(redisCode)) {
            //2.1 返回错误
            return ResponseEntity.status(500).body(ErrorResult.error());
        }
        // 删除验证码
        redisTemplate.delete(SMS_KEY+phone);

        //3. 根据手机号码查询数据库
        User user = userApi.findByMobile(phone);
        Boolean isNew = false;
        // 【发送mq消息用到的操作类型：0101表示登陆】
        String type = "0101";
        //3.1 判断手机号码如果不存在，就自动注册
        if (user == null) {
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            // 保存用户
            Long userId = userApi.save(user);
            user.setId(userId);
            // 设置为新用户
            isNew = true;

            // 新用户同时注册到环信
            huanXinTemplate.register(user.getId());

            //【注册】
            type = "0102";
        }


        // 【发送mq消息，消息内容：userId、type、date】
        // 【后续：交给tanhua-manage项目消费消息，获取日志数据，录入到tb_log日志表】
        Map<String,String> map = new HashMap<>();
        map.put("userId",user.getId()+"");
        map.put("type",type);
        map.put("date",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        // 发送消息  参数1：主题； 参数2：消息内容
        rocketMQTemplate.convertAndSend("tanhuan-log", JSON.toJSONString(map));

        // 生成token
        String token = JwtUtils.createToken(user.getId(), phone, secret);
        // 把token信息以及对应的用户信息存储到redis中
        // 对象转json
        String userJsonString = JSON.toJSONString(user);
        // 存储到redis
        redisTemplate.opsForValue().set("TOKENY_KEY_"+token,userJsonString, Duration.ofHours(4));

        //4. 返回
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);
        return ResponseEntity.ok(resultMap);
    }

    /**
     * 接口名称：新用户---1填写资料
     */
    public ResponseEntity saveUserInfo(UserInfo userInfo, String token) {
        //1. 根据请求参数token，获取用户信息
        User user = this.findUserByToken(token);
        if (user == null) {
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        //2. 设置用户详情id，保存用户详情
        userInfo.setId(user.getId());
        // 保存用户详情
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    public User findUserByToken(String token){
        String userJsonString = redisTemplate.opsForValue().get("TOKENY_KEY_"+token);
        if (userJsonString == null) {
            return null;
        }
        User user = JSON.parseObject(userJsonString, User.class);
        // 更新token的有效时间
        redisTemplate.opsForValue().set("TOKENY_KEY_"+token,userJsonString,Duration.ofHours(4));
        return user;
    }

    /**
     * 接口名称：新用户---2选取头像
     */
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto, String token) throws IOException {
        //1. 根据token获取用户
        User user = findUserByToken(token);

        //2. 图片人脸检测
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            // 人脸识别校验错误
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //3. 拍摄的人脸上传到阿里云oss
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //4. 修改用户详情（头像信息）
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(url);
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：用户资料 - 读取
     */
    public ResponseEntity<Object> findUserInfoById() {
        // 1. 根据token获取用户
        //User user = findUserByToken(token);
        User user = UserHolder.get();

        // 2. 根据用户id查询用户详情：UserInfo
        UserInfo userInfo = userInfoApi.findById(user.getId());

        // 3. 返回的数据通过vo封装
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo,userInfoVo);
        // 处理年龄类型不一致
        if (userInfo.getAge() != null) {
            userInfoVo.setAge(userInfo.getAge().toString());
        }
        return ResponseEntity.ok(userInfoVo);
    }

    /**
     * 接口名称：用户资料 - 保存
     */
    public ResponseEntity<Object> updateUserInfo(UserInfo userInfo, String token) {
        //1. 根据token获取用户
        User user = findUserByToken(token);
        //2. 更新用户
        userInfo.setId(user.getId());
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    @Reference
    private UserLikeApi userLikeApi;

    public ResponseEntity<Object> queryCounts() {
        //1. 获取登陆用户id
        Long userId = UserHolder.getUserId();

        //2. 查询统计
        //2.1 统计互相喜欢
        Long eachLoveCount = userLikeApi.queryEachLoveCount(userId);
        //2.2 统计喜欢
        Long loveCount = userLikeApi.queryLoveCount(userId);
        //2.3 统计粉丝
        Long fanCount = userLikeApi.queryFanCount(userId);

        //3. 返回结果
        Map<String,Integer> resultMap = new HashMap<>();
        resultMap.put("eachLoveCount",eachLoveCount.intValue());
        resultMap.put("loveCount",loveCount.intValue());
        resultMap.put("fanCount",fanCount.intValue());
        return ResponseEntity.ok(resultMap);
    }

    /**
     * 接口名称：互相喜欢、喜欢、粉丝、谁看过我  (列表)
     * 互相喜欢:   db.tanhua_users.find({userId:20})
     * 喜欢:      db.user_like.find({userId:20})
     * 粉丝：     db.user_like.find({likeUserId:20})
     * 谁看过我 :  db.visitors.find({userId:20})
     */
    public ResponseEntity<Object> queryUserLikeList(Integer type, Integer page, Integer pagesize) {
        //1. 获取登陆用户id
        Long userId = UserHolder.getUserId();

        PageResult pageResult = null;
        //2. 根据类型判断
        switch (type) {
            case 1:
                pageResult = userLikeApi.queryEachLoveList(userId,page,pagesize);
                break;
            case 2:
                pageResult = userLikeApi.queryLoveList(userId,page,pagesize);
                break;
            case 3:
                pageResult = userLikeApi.queryFanList(userId,page,pagesize);
                break;
            case 4:
                pageResult = userLikeApi.queryVisitorList(userId,page,pagesize);
                break;
        }

        //3. 获取查询结果
        List<Map<String,Object>> list = (List<Map<String, Object>>) pageResult.getItems();

        //4. 封装返回结果
        List<UserLikeVo> voList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (Map<String, Object> map : list) {
                // 获取用户id、缘分值
                Long uid = (Long) map.get("userId");
                Long score = (Long) map.get("score");

                // 创建vo
                UserLikeVo userLikeVo = new UserLikeVo();
                // 根据用户id查询
                UserInfo userInfo = userInfoApi.findById(uid);
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo,userLikeVo);
                }
                // 设置缘分值
                userLikeVo.setMatchRate(score.intValue());
                // 添加到集合
                voList.add(userLikeVo);
            }
        }

        //5. 把封装的返回结果设置到pageRequest中
        pageResult.setItems(voList);
        return ResponseEntity.ok(pageResult);
    }

    @Reference
    private FriendApi friendApi;

    /**
     * 接口名称：粉丝 - 喜欢
     */
    public ResponseEntity<Object> fanLike(Integer likeUserId) {
        Long userId = UserHolder.getUserId();
        //1. 删除粉丝表中的数据
        userLikeApi.delete(likeUserId, userId);
        //2. 记录好友的关系
        friendApi.save(userId,likeUserId.longValue());
        //3. 注册好友关系到环信
        huanXinTemplate.contactUsers(userId,likeUserId.longValue());
        return ResponseEntity.ok(null);

    }

    /**
     * 修改手机号 - 2 校验验证码
     */
    public ResponseEntity<Object> checkVerificationCode(String code) {
        //1. 获取用户信息
        User user = UserHolder.get();

        //2. 从redis中获取验证码
        String key = SMS_KEY + user.getMobile();
        String redisCode = redisTemplate.opsForValue().get(key);

        //3. 判断
        Boolean verification = true;
        if (code == null || redisCode == null || !redisCode.equals(code)) {
            //3.1 校验失败
            verification = false;
        } else {
            //3.2 校验成功，从redis中删除验证码
            redisTemplate.delete(key);
        }

        //4. 构造返回结果:{"verification":false/true}
        Map<String,Boolean> resultMap = new HashMap<>();
        resultMap.put("verification",verification);
        return ResponseEntity.ok(resultMap);
    }


    /**
     * 修改手机号 - 3 保存
     * @param phone 修改后的手机号
     * @return
     */
    public ResponseEntity<Object> updateUserPhone(String phone) {
        //1. 根据修改后的手机号码查询，如果手机号码已经存在返回错误信息
        User user = userApi.findByMobile(phone);
        if (user != null) {
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }

        //2. 获取用户信息、设置修改手机号
        User updateUser = UserHolder.get();
        updateUser.setMobile(phone);

        //3. 修改用户
        userApi.update(updateUser);
        return ResponseEntity.ok(null);
    }


    public ResponseEntity<Object> sendSms(Map<String, String> paramMap) {
        try {
            //1. 获取手机号
            String phone = paramMap.get("phone");
            //这里从redis中获取验证码判断是否失效
            String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);
            if (!StringUtils.isEmpty(redisCode)) {
                //返回上一次验证码未失效
                return ResponseEntity.status(500).body(ErrorResult.duplicate());
            }
            //2. 生成6位随机数
//            String code = RandomStringUtils.randomNumeric(6);
            //3. 发送短信验证码
            smsTemplate.sendSms(phone, "123456");
            //4. 验证码存储到redis中，key是: SMS_KEY_ + 手机号; 有效时间5分钟
            redisTemplate.opsForValue().set(SMS_KEY + phone, "123456", Duration.ofMinutes(5));
            //发送成功
            return ResponseEntity.ok(null);
        } catch (Exception e) {
            e.printStackTrace();
            //发送验证码失败
            return ResponseEntity.status(500).body(ErrorResult.fail());
        }
    }
}


















